package com.wyg.epdata.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wyg.epdata.controller.CompanyDataController;
import com.wyg.epdata.controller.DataController;
import com.wyg.epdata.entity.ArticleEntity;
import com.wyg.epdata.entity.CompanyIntro;
import com.wyg.epdata.entity.CompanyNum;
import com.wyg.epdata.entity.DataResult;
import com.wyg.epdata.entity.dto.HotSort;
import com.wyg.epdata.entity.dto.KwCountDTO;
import com.wyg.epdata.entity.excel.DataResultXLS;
import com.wyg.epdata.entity.reqDto.EntityReq;
import com.wyg.epdata.entity.reqDto.ExcelParamDTO;
import com.wyg.epdata.entity.vo.CountByDate;
import com.wyg.epdata.util.JsonUtil;
import com.wyg.epcommonbase.common.enums.PdfTheme;
import com.wyg.epcommonbase.common.util.BeanMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * @Author: WangYongGan
 * @Date: 2022/3/30 14:18
 * @Description:
 */
@Service
public class FileService {
    @Autowired
    ArticleEntityService articleEntityService;
    @Autowired
    DataResultService dataResultService;
    @Autowired
    DataController dataController;
    @Autowired
    CompanyDataController companyDataController;
    @Autowired
    ICompanyIntroService iCompanyIntroService;
    @Autowired
    CompanyDataService companyDataService;
    @Autowired
    CompanyNumService companyNumService;
    @Autowired
    ArticleKwService articleKwService;

    @SneakyThrows
    public JSONObject[] downPdf(EntityReq req, HttpServletResponse response) {
        CountDownLatch countDownLatch = new CountDownLatch(4);
        String entity = req.getEntity();
        JsonUtil jsonObject = new JsonUtil();
        CompanyIntro companyIntro = Optional.ofNullable(iCompanyIntroService.getOne(new QueryWrapper<CompanyIntro>().eq("name", entity))).orElse(new CompanyIntro());
        jsonObject.put("name", entity);
        jsonObject.putOrNullZh("company", companyIntro.getName());
        jsonObject.putOrNullZh("intro", companyIntro.getIntro());
        //最近新闻
        List<news> newsList = new ArrayList<>();
        new Thread(() -> {
            List<DataResult> dataResults = dataResultService.
                    list(new QueryWrapper<DataResult>().like("entity", entity).
                            gt(req.getBegin() != null, "created_at", req.getBegin()).
                            lt(req.getEnd() != null, "created_at", req.getEnd())
                            .orderByDesc("created_at").last("limit " + req.getN()));
            SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd");
            if (!CollectionUtils.isEmpty(dataResults))
                dataResults.forEach(o -> {
                    news ne = new news();
                    ne.setDate(sdf.format(o.getCreatedAt()));
                    ne.setReg(o.isReg());
                    ne.setRawText(o.getRawText());
                    newsList.add(ne);
                });
            countDownLatch.countDown();
        }).start();
        //正负面
        KW kw = new KW();
        new Thread(() -> {
            //关键字
            List<KwCountDTO> nKwByEntity = Optional.ofNullable(articleKwService.getNKwByEntity(entity, 10)).orElse(new ArrayList<>());
            List<pie> series = new ArrayList<>();
            List<String> legend = new ArrayList<>();
            nKwByEntity.forEach(kW -> {
                series.add(new pie(kW.getCount(), kW.getKw()));
                legend.add(kW.getKw());
            });
            kw.setLegend(legend);
            kw.setSeries(series);
            countDownLatch.countDown();
        }).start();
        //百科介绍
        JsonUtil json2 = new JsonUtil();
        new Thread(() -> {
            final String[] keys = companyIntro.getBaikeKey().split("<-wyg->");
            final String[] values = companyIntro.getBaikeValue().split("<-wyg->");
            for (int i = 0; i < keys.length; i++) {
                json2.put(keys[i], values[i]);
            }
            countDownLatch.countDown();
        }).start();
        //热度
        HotSort hotSort = new HotSort();
        //正负比
        List<pie> regRatio = new ArrayList<>();
        new Thread(() -> {
            CompanyNum companyNum = Optional.ofNullable(companyNumService.getCountOfCompany(entity)).orElse(new CompanyNum());
            regRatio.add(new pie(companyNum.getAllNum() - companyNum.getRegNum(), "正面"));
            regRatio.add(new pie(companyNum.getRegNum(), "负面"));
            companyNumService.getHotSort(entity, hotSort);
            countDownLatch.countDown();
        }).start();
        //趋势
        Map<String, Integer> dateMap = getMonthDate(req.getBegin(), req.getEnd());
        String end = dateMap.keySet().stream().max(String::compareTo).get();
        String begin = dateMap.keySet().stream().min(String::compareTo).get();
        List<CountByDate> monthCountByDate = Optional.ofNullable(companyDataService.getMonthCountByDate(begin, end, entity)).orElse(new ArrayList<>());
        Random r = new Random();
        for (CountByDate countByDate : monthCountByDate) {
            String key = countByDate.getDate().substring(0, 7);
            dateMap.put(key, countByDate.getSum() + r.nextInt(20));
        }
        /**
         * 主题
         *@param theme vintage  dark  macarons  infographic  shine  roma
         */
        countDownLatch.await();
        int themeNum = req.getParam().get("themeNum") == null ? 1 : (int) req.getParam().get("themeNum");
        jsonObject.put("theme", PdfTheme.getByNum(themeNum).name());
        jsonObject.put("news", newsList);
        jsonObject.put("regRatio", regRatio);
        jsonObject.put("hotSort", companyNumService.getHotSort(entity));
        jsonObject.put("kw", kw);
        jsonObject.put("hotSort", hotSort);

        jsonObject.put("trend", new trend(dateMap.keySet(), dateMap.values()));
        System.out.println(jsonObject.toJSONString());

        return new JSONObject[]{jsonObject, json2};
    }

    @SneakyThrows
    public void downExcel(ExcelParamDTO excelParam, HttpServletResponse response) {
        QueryWrapper<ArticleEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("entity", excelParam.getEntity());
        if (excelParam.getNum() != 0)
            wrapper.last(" limit " + excelParam.getNum());
        List<ArticleEntity> list = articleEntityService.list(wrapper);
        List<String> ids = list.stream().map(ArticleEntity::getArticleId).collect(Collectors.toList());
        QueryWrapper<DataResult> wrapper1 = new QueryWrapper<>();
        wrapper1.in("article_id", ids);
        List<DataResult> dataResults = dataResultService.list(wrapper1);
        List<DataResultXLS> dataResultXLS = BeanMapper.copyList(dataResults, DataResultXLS::new);
        dataResultXLS.forEach(o -> {
            if (StringUtils.isBlank(o.getTitle())) o.setTitle("无");
        });
        String fileName = URLEncoder.encode("ESData", "UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        // excel头策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 11);
        headWriteFont.setBold(false);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // excel内容策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 11);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 设置handler
        HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        /** 导出数据查询方法*/
        EasyExcel.write(response.getOutputStream(), dataResultXLS.get(0).getClass())
                .sheet("下载excel服务")
                .registerWriteHandler(styleStrategy)
                .doWrite(dataResultXLS);
    }

    public Map<String, Integer> getMonthDate(String begin, String end) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        String format = sdf.format(date);
        int month = Integer.parseInt(begin.split("-")[1]);
        int year = Integer.parseInt(begin.split("-")[0]);
        LinkedHashMap<String, Integer> dateMap = new LinkedHashMap<>();
        int endYear = Integer.parseInt(end.split("-")[0]);
        int endMonth = Integer.parseInt(end.split("-")[1]);
        for (int i = 12 * (endYear - year) + endMonth - month; i >= 0; i--) {
            int tempMonth = endMonth - i;
            int tempYear = endYear;
            if (tempMonth <= 0) {
                tempMonth += 12;
                tempYear -= 1;
            }
            StringBuffer sb = new StringBuffer();
            sb.append(tempYear);
            sb.append("-");
            sb.append(get10(tempMonth));
            dateMap.put(sb.toString(), 0);
        }
        return dateMap;
    }

    public static String get10(int n) {
        return String.valueOf(100 + n).substring(1);
    }
}

@Data
@NoArgsConstructor
class news {
    @JSONField(name = "isReg")
    private boolean isReg;
    @JSONField(name = "date")
    private String date;
    @JSONField(name = "rawText")
    private String rawText;

    public news(boolean isReg, String rawText) {
        this.rawText = rawText;
        this.isReg = isReg;
    }

}

@Data
class pie {
    int value;
    String name;

    public pie(int value, String name) {
        this.value = value;
        this.name = name;
    }
}

@Data
@AllArgsConstructor
class trend {
    Set<String> date;
    Collection<Integer> nums;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class KW {
    List<pie> series;
    List<String> legend;
}
